/*
 * @Author: _oufen
 * @Date: 2023-07-03 13:31:06
 * @LastEditTime: 2023-07-08 09:24:50
 * @Description:
 */
#include "stm32f10x.h" // Device header
#include "sr04.h"
#include "delay.h"
#include "usart.h"
#include "LED.h"

// 超声波  trig PB7     Echo    PB6
// 捕获通道 TIM4-CH1

/**
 * @brief 	SR04初始化 开启时钟 选择端口 初始化GPIO口   PB7
 * @param 	无
 * @retval  无
 */
void SR04_GPIO_Init(void) // PB7
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_SetBits(GPIOB, GPIO_Pin_7);
}

/**
 * @brief 	输入捕获通道   PB6 输入捕获  TIM4-CH1
 * @param 	无
 * @retval  无
 */
// 定时器4通道1输入捕获配置

void TIM4_Cap_Init(u16 arr, u16 psc)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_ICInitTypeDef TIM4_ICInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);  // 使能TIM4时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能GPIOB时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;             // PB6 清除之前设置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;         // PB6 输入  下拉输入
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_ResetBits(GPIOB, GPIO_Pin_6); // PB6 下拉

    // 初始化定时器4 TIM5
    TIM_TimeBaseStructure.TIM_Period = arr;                     // 设定计数器自动重装值
    TIM_TimeBaseStructure.TIM_Prescaler = psc;                  // 预分频器
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;     // 设置时钟分割:TDTS = Tck_tim
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // TIM向上计数模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);             // 根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

    // 初始化TIM4输入捕获参数
    TIM4_ICInitStructure.TIM_Channel = TIM_Channel_1;                // 捕获通道1
    TIM4_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;     // 上升沿捕获
    TIM4_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // 映射到TI2上
    TIM4_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;           // 配置输入分频,不分频
    TIM4_ICInitStructure.TIM_ICFilter = 0x00;                        // IC1F=0000 配置输入滤波器 不滤波
    TIM_ICInit(TIM4, &TIM4_ICInitStructure);

    // 中断分组初始化
    NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;           // TIM4中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; // 先占优先级2级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        // 从优先级0级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           // IRQ通道被使能
    NVIC_Init(&NVIC_InitStructure);                           // 根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器在time 中声明初始化函数
    TIM_ITConfig(TIM4, TIM_IT_Update | TIM_IT_CC1, ENABLE);   // 允许更新中断 ,允许CC2IE捕获中断     这里要注意  移植时注意 对应哪个通道 就要选择哪个CCX
    TIM_Cmd(TIM4, ENABLE);                                    // 使能定时器2
}

/**
 * @brief 	超声波初始化
 * @param 	无
 * @retval  无
 */
void Sr04_All_Init(void)
{
    SR04_GPIO_Init();             // 超声波 IO 初始化       Trig初始化
    TIM4_Cap_Init(65535, 72 - 1); // 捕获通道初始化         Echo初始化
}

u8 TIM5CH1_CAPTURE_STA = 0; // 输入捕获状态
u16 TIM5CH1_CAPTURE_VAL;    // 输入捕获值
// 定时器2中断服务程序
void TIM4_IRQHandler(void)
{
    // Buzzer_IN = 1;
    if ((TIM5CH1_CAPTURE_STA & 0X80) == 0) // 还未成功捕获
    {
        if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
        {
            if (TIM5CH1_CAPTURE_STA & 0X40) // 已经捕获到高电平了
            {
                if ((TIM5CH1_CAPTURE_STA & 0X3F) == 0X3F) // 高电平太长了
                {
                    TIM5CH1_CAPTURE_STA |= 0X80; // 标记成功捕获了一次
                    TIM5CH1_CAPTURE_VAL = 0XFFFF;
                }
                else
                    TIM5CH1_CAPTURE_STA++;
            }
        }
        if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET) // 捕获2发生捕获事件
        {
            if (TIM5CH1_CAPTURE_STA & 0X40) // 捕获到一个下降沿
            {
                TIM5CH1_CAPTURE_STA |= 0X80;                        // 标记成功捕获到一次上升沿
                TIM5CH1_CAPTURE_VAL = TIM_GetCapture1(TIM4);        // 移植时这里也要注意  TIM4的通道1
                TIM_OC1PolarityConfig(TIM4, TIM_ICPolarity_Rising); // CC2P=0 设置为上升沿捕获     移植时 这里也要注意  TIM4上升沿
            }
            else // 还未开始,第一次捕获上升沿
            {
                TIM5CH1_CAPTURE_STA = 0; // 清空
                TIM5CH1_CAPTURE_VAL = 0;
                TIM_SetCounter(TIM4, 0);
                TIM5CH1_CAPTURE_STA |= 0X40;                         // 标记捕获到了上升沿
                TIM_OC1PolarityConfig(TIM4, TIM_ICPolarity_Falling); // CC2P=1  设置为下降沿捕获    TIM4通道1 上升沿
            }
        }
    }
    TIM_ClearITPendingBit(TIM4, TIM_IT_CC1 | TIM_IT_Update); // 清除中断标志位
}

int Distance = 0;
int time = 0;

int Get_SR04_Distance(void) // 获取SR04捕获的距离和高电平时间
{
    HC_SR04 = 1;
    delay_us(13);
    HC_SR04 = 0;
    if (TIM5CH1_CAPTURE_STA & 0X80) // 成功捕获到了一次上升沿
    {
        time = TIM5CH1_CAPTURE_STA & 0X3F;
        time *= 65536;               // 溢出时间总和
        time += TIM5CH1_CAPTURE_VAL; // 得到总的高电平时间
        // printf("\r\nHIGH:%d us\r\n", time); // 打印总的高点平时间
        //u1_printf("\r\nHIGH: %d us\r\n", time);
        Distance = time * 0.033 / 2;
        // printf("cm:%d\r\n", Distance);
        //u1_printf("cm: %d\r\n", Distance);
        TIM5CH1_CAPTURE_STA = 0; // 开启下一次捕获
		
		if(Distance>40)
		{
			Distance=40;
		}
    }
    return Distance;
}
